﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TracyGUI.UIComponent;
using Tracy.DataModel;
using System.ComponentModel;
using Tracy;
using Tracy.Messages;
using Tracy.Handlers;
using SharedLib.MessageFramework;
using System.IO;
using SharedLib.Helpers;
using System.Drawing;

namespace TracyGUI
{
    public partial class FormMain
    {
        private Dictionary<string, ListBoxItemEntry> _mappingEntry = new Dictionary<string, ListBoxItemEntry>();
        TabPageEntry _selectedEntryPage = null;
        Entry _lastSelectedEntry = null; //Use for saving changes to previous selected entry
        bool _isUpdatingEntry = false;


        private void listBoxEntries_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_isUpdatingEntry)
            {
                if (GetSelectedEntry() != null)
                {
                    if (IsTagEditing()) ApplyTagChange();
                }

                Entry entry = GetSelectedEntry(false);
                if (entry != null)
                {
                    _lastSelectedEntry = entry;
                    if (Control.ModifierKeys == Keys.Control)
                    {
                        OpenEntryInNewTab(entry);
                    }
                    else
                    {
                        //TODO: Improve performance

                        if (_selectedEntryPage == null)
                        {
                            _selectedEntryPage = CreateEntryTab(entry.ID);
                            _tabControlContent.TabPages.Add(_selectedEntryPage);
                        }
                        else LoadDataToEntryTab(_selectedEntryPage, entry.ID);
                        _tabControlContent.SelectedTab = _selectedEntryPage;
                    }

                    ShowTagPanel(entry);
                }
                
            }

        }

        
        private void LoadEntries()
        {
            InitEntryTabs();
        }

        private void ReloadEntriesToList(List<Entry> entries)
        {
            listBoxEntries.SelectedIndex = -1;
            listBoxEntries.Items.Clear();
            _mappingEntry.Clear();
            foreach (Entry entry in entries)
            {
                AddEntryToList(entry);   
            }
        }

        private void toolStripButtonShowAll_Click(object sender, EventArgs e)
        {
            if (!_tabControlContent.TabPages.ContainsKey(TabPageEntry.TABPAGE_NAME_ALL))
            {
                _tabControlContent.TabPages.Add(CreateEntryTab(TabPageEntry.TABPAGE_NAME_ALL));
            }
            _tabControlContent.SelectTab(TabPageEntry.TABPAGE_NAME_ALL);
        }

        

        private void ShowFormEntry(FormEntry.EntryEditMode mode)
        {
            //TODO: Refactor this logic
            FormEntry formEntry;
            Entry entry = GetSelectedEntry();
            string previousPath = null;
            if (entry != null && mode == FormEntry.EntryEditMode.Modify)
            {

                previousPath = entry.SavePath;
                formEntry = new FormEntry(mode, entry);
            }
            else
            {
                formEntry = new FormEntry(mode, null);
            }
            if (formEntry.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {

                if (mode == FormEntry.EntryEditMode.Modify) // Modify Entry
                {
                    //Entry originalEntry = TracyBus.Instance.EntryProvider.GetItemByID(formEntry.EditingEntry.ID);
                    var removedItemInfo = BeginUpdateEntryInList(formEntry.EditingEntry);
                    //Applying change
                    TracyFacade.Instance.EntryProvider.UpdateItem(formEntry.EditingEntry);
                    TracyFacade.Instance.FilterManager.FilterProvider.SetFilterSets(formEntry.SelectedFilterSets, formEntry.EditingEntry);
                    EndUpdateEntryInList(removedItemInfo);

                    if (previousPath != null && previousPath != formEntry.EditingEntry.SavePath)
                    {
                        //SavePath Changed
                        if (MessageBox.Show("Save path changed, would you like to move the files to the new location?", "Changing save path", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                        {
                            MoveMediaFiles(formEntry.EditingEntry, previousPath);
                        }
                    }
                }
                else //Create Entry
                {
                    TracyFacade.Instance.EntryProvider.AddItem(formEntry.EditingEntry);
                    TracyFacade.Instance.FilterManager.FilterProvider.SetFilterSets(formEntry.SelectedFilterSets, formEntry.EditingEntry);
                    AddEntryToList(formEntry.EditingEntry);
                    _ueEntry.UpdateTreeForItemChange(formEntry.EditingEntry);
                    listBoxEntries.SelectedIndex = 0;
                }

                //Trigger Scan for this entry
                TaskMessage taskMsg = new TaskMessage(this, typeof(FeedScanHandler), formEntry.EditingEntry, null);
                TracyFacade.Instance.MessageDispatcher.EnqueueMessage(taskMsg);

                string savePath = formEntry.EditingEntry.SavePath;
                RememberLastSavePath(savePath);
                //TODO: Work out a efficient way to sync UI and db
                
            }
        }

        private void RememberLastSavePath(string savePath)
        {
            if (!String.IsNullOrEmpty(savePath) && savePath != TracyFacade.Instance.UserPreferenceManager.SavePath)
            {
                int index = savePath.TrimEnd('\\').LastIndexOf('\\');
                if (index > 0) savePath = savePath.Remove(index);
                TracyFacade.Instance.UserPreferenceManager.SavePath = savePath;
            }
        }

        private void MoveMediaFiles(Entry entry, string previousPath)
        {
            if (entry != null && !String.IsNullOrEmpty(previousPath))
            {
                lock (_lockHelperFileMove)
                {
                    foreach (MediaFile file in TracyFacade.Instance.MediaFileProvider.GetItemByEntry(entry))
                    {
                        if (file.Status == "Watched" || file.Status == "Ready")
                        {
                            file.Properties[MediaFile.KEY_PREVIOUS_STATUS] = file.Status;
                            file.Status = "Moving";
                            file.Properties[MediaFile.KEY_PREVIOUS_PATH] = previousPath;
                            TracyFacade.Instance.MediaFileProvider.UpdateItem(file);
                            TracyFacade.Instance.MessageDispatcher.EnqueueMessage(new TaskMessage(this, typeof(FileMonitorHandler), file, null));

                            if (filesInPath.ContainsKey(previousPath)) filesInPath[previousPath]++;
                            else filesInPath[previousPath] = 1;
                        }
                    }
                }
            }
            //TODO:Remove folder and handle exception
        }

        private object _lockHelperFileMove = new object();
        private Dictionary<string, int> filesInPath = new Dictionary<string,int>();

        //Delete original folder, triggered by OnFileUpdated
        private void FileMoved(MediaFile copiedFile)
        {
            if (copiedFile != null)
            {
                if (copiedFile.Properties.ContainsKey(MediaFile.KEY_PREVIOUS_PATH))
                {
                    lock (_lockHelperFileMove)
                    {
                        string previousPath = copiedFile.Properties[MediaFile.KEY_PREVIOUS_PATH];
                        copiedFile.Properties.Remove(MediaFile.KEY_PREVIOUS_PATH);
                        TracyFacade.Instance.MediaFileProvider.UpdateItem(copiedFile);

                        if (filesInPath.ContainsKey(previousPath))
                        {
                            filesInPath[previousPath]--;
                            if (filesInPath[previousPath] <= 0)
                            {
                                filesInPath.Remove(previousPath);
                                //Remove Folder
                                IOHelper.DeleteFolderIfNotEmpty(previousPath);
                            }
                        }
                    }
                    
                }
            }
        }

        //private void UpdateEntryInList(Entry originalEntry, Entry newEntry)
        //{
        //    if (newEntry.ID != originalEntry.ID) throw new Exception("Failed to update entry - ID not match: " + originalEntry.ID + " to " + newEntry.ID);
        //    if (_mappingEntry.ContainsKey(newEntry.ID))
        //    {
        //        _isUpdatingEntry = true;
                
                
                
        //         = previousSelectedIndex;
                
        //        _isUpdatingEntry = false;
        //    }
        //}

        private dynamic BeginUpdateEntryInList(Entry entry)
        {
            if (_mappingEntry.ContainsKey(entry.ID))
            {
                var rtn = new
                {
                    PreviousSelectedIndex = listBoxEntries.SelectedIndex,
                    OldIndex = RemoveEntryFromList(entry),
                    EntryID = entry.ID
                };
                return rtn;
            }
            return null;
        }

        private void EndUpdateEntryInList(dynamic removedItemInfo)
        {
            if (removedItemInfo != null)
            {
                Entry entry = TracyFacade.Instance.EntryProvider.GetItemByID(removedItemInfo.EntryID);
                AddEntryToList(entry, removedItemInfo.OldIndex);
                _isUpdatingEntry = true;
                listBoxEntries.SelectedIndex = removedItemInfo.PreviousSelectedIndex;
                _isUpdatingEntry = false;
                _ueEntry.UpdateTreeForItemChange(entry);
            }
        }

        private List<Entry> GetEntriesInList()
        {
            List<Entry> rtn = new List<Entry>();
            foreach (ListBoxItemEntry item in listBoxEntries.Items)
            {
                Entry entry = item.Data as Entry;
                if (entry != null)
                {
                    rtn.Add(entry);
                }
            }
            return rtn;
        }

        private void AddEntryToList(Entry entry, int index = 0)
        {
            ListBoxItemEntry item = new ListBoxItemEntry(entry);
            listBoxEntries.Items.Insert(index, item);
            _mappingEntry.Add(entry.ID, item);
        }

        private int RemoveEntryFromList(Entry entry)
        {
            int oldIndex = listBoxEntries.Items.IndexOf(_mappingEntry[entry.ID]);
            if (oldIndex < 0) return oldIndex;

            listBoxEntries.Items.RemoveAt(oldIndex);
            _mappingEntry.Remove(entry.ID);
            
            return oldIndex;
        }

        private void toolStripButtonAddEntry_Click(object sender, EventArgs e)
        {
            ShowFormEntry(FormEntry.EntryEditMode.Create);
        }

        private void toolStripMenuItemAddEntry_Click(object sender, EventArgs e)
        {
            ShowFormEntry(FormEntry.EntryEditMode.Create);
        }

        private void contextMenuStripEntry_Opening(object sender, CancelEventArgs e)
        {
            if (listBoxEntries.SelectedIndex == -1)
            {
                toolStripMenuItemModifyEntry.Enabled = false;
                toolStripMenuItemRemoveEntry.Enabled = false;
            }
            else
            {
                toolStripMenuItemModifyEntry.Enabled = true;
                toolStripMenuItemRemoveEntry.Enabled = true;
            }
        }

        private void listBoxEntries_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (GetSelectedEntry() != null)
            {
                ShowFormEntry(FormEntry.EntryEditMode.Modify);
            }
        }

        private void toolStripMenuItemModifyEntry_Click(object sender, EventArgs e)
        {
            ShowFormEntry(FormEntry.EntryEditMode.Modify);
        }
        private void listBoxEntries_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)//Select item on right click
            {
                int selectedIndex = listBoxEntries.IndexFromPoint(e.X, e.Y);
                if (selectedIndex != -1)
                {
                    listBoxEntries.SelectedIndex = selectedIndex;
                }
            }
        }
        private void toolStripMenuItemRemoveEntry_Click(object sender, EventArgs e)
        {
            Entry entry = GetSelectedEntry();
            if (entry != null)
            {
                //listBoxEntries.Items.Remove(item);
                listBoxEntries.SelectedIndex = -1;
                RemoveEntryFromList(entry);
                RemoveEntryTab(entry);
                RemoveEntryAction(entry);
                _ueEntry.UpdateTreeForItemChange(entry);
            }
        }



        private void RemoveEntryAction(Entry entry)
        {
            //_mappingEntry.Remove(entry.ID);
            List<Resource> resourcesToRemove = TracyFacade.Instance.ResourceProvider.GetItemByEntry(entry);
            RemoveResourcesAction(resourcesToRemove);
            TracyFacade.Instance.EntryProvider.RemoveItem(entry.ID);
            IOHelper.DeleteFolderIfNotEmpty(entry.SavePath);
        }

        private void openInNewTabToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenEntryInNewTab(GetSelectedEntry());
        }

        private void OpenEntryInNewTab(Entry entry)
        {
            if (entry != null)
            {
                TabPageEntry tab = CreateEntryTab(entry.ID);
                _tabControlContent.TabPages.Add(tab);
                _tabControlContent.SelectedTab = tab;
            }
        }

        private Entry GetSelectedEntry(bool useCachedValue = true)
        {
            if (useCachedValue) return _lastSelectedEntry;

            if (listBoxEntries.SelectedIndex != -1)
            {
                ListBoxItemEntry item = listBoxEntries.SelectedItem as ListBoxItemEntry;
                if (item != null && item.Data != null && item.Data is Entry)
                {
                    _lastSelectedEntry = item.Data as Entry;;
                }
            }
            return _lastSelectedEntry;
        }

        private void listBoxEntries_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index >= 0)
            {
                e.DrawBackground();
                ListBoxItemEntry item = listBoxEntries.Items[e.Index] as ListBoxItemEntry;
                if (item != null)
                {
                    Font myFont = e.Font;
                    Brush myBrush = SystemBrushes.WindowText;
                    if (item.Data.TracingDisabled) myBrush = SystemBrushes.GrayText;
                    if (item.UnWatchedCount > 0) myBrush = Brushes.DarkRed; //myFont = new Font(myFont, FontStyle.Bold);
                    e.Graphics.DrawString(item.ToString(), myFont, myBrush, e.Bounds, StringFormat.GenericDefault);
                }
                e.DrawFocusRectangle();
            }
        }


    }
}
